package edu.cs.usask.ca.silver.businesslogic.commands.generic;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.UUID;

import org.apache.log4j.Logger;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.vensim.Vensim;

import edu.cs.usask.ca.silver.api.businesslogic.ModelVersionI;
import edu.cs.usask.ca.silver.api.persistence.StorageI;
import edu.cs.usask.ca.silver.businesslogic.ids.FileID;
import edu.cs.usask.ca.silver.businesslogic.ids.ModelProjectID;
import edu.cs.usask.ca.silver.businesslogic.ids.ModelVersionID;
import edu.cs.usask.ca.silver.businesslogic.ids.ScenarioCollectionID;
import edu.cs.usask.ca.silver.businesslogic.ids.ScenarioID;
import edu.cs.usask.ca.silver.businesslogic.util.SilverAutoManagedObjectFactory;
import edu.cs.usask.ca.silver.businesslogic.util.SilverBLTransactionManager;
import edu.cs.usask.ca.silver.definitions.SupportedModelType;
import edu.cs.usask.ca.silver.definitions.SystemProperties;
import edu.cs.usask.ca.silver.exceptions.SilverBusinessLogicErrorException;
import edu.cs.usask.ca.silver.util.parsers.fileparsers.AlpFileReader;
import edu.cs.usask.ca.silver.util.parsers.fileparsers.JarBuilder;

public class ModelVersion implements ModelVersionI {

	private static final SilverAutoManagedObjectFactory mvFactory = new SilverAutoManagedObjectFactory(
			"edu.cs.usask.ca.silver.businesslogic.commands.generic.ModelVersion");

	private static Logger logger = Logger.getLogger(ModelVersion.class);

	// TODO to be moved to Anylogic ModelVersion
	private AlpFileReader alpParser;

	protected enum ParameterEnum {
		NAME(0), TYPE(1), CLASS(2), VALUE(3), IS_VISIBLE(1);

		private int index;

		private ParameterEnum(int c) {
			index = c;
		}

		public int index() {
			return index;
		}
	}

	public static SilverAutoManagedObjectFactory getObjectPoolFactory() {
		return mvFactory;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ModelVersionI#createModelVersion
	 * (java.lang.String, java.lang.String, java.lang.String,
	 * edu.cs.usask.ca.silver.businesslogic.ids.ModelProjectID)
	 */
	@Override
	public ModelVersionID createGenericModelVersion(String vName,
			String vCreator, String vDescr, ModelProjectID mpId,
			StorageI storage) throws Exception {
		UUID mvId = storage.addModelVersion(vName, vCreator,
				SupportedModelType.GENERIC.toString(), vDescr,
				mpId.getUUIdVal(), SystemProperties.IS_VISIBLE);
		return new ModelVersionID(mvId);
	}

	@Override
	public ModelVersionID createVensimModelVersion(String vName,
			String vCreator, String vDescr, ModelProjectID mpId,
			StorageI storage) throws Exception {
		UUID mvId = storage.addModelVersion(vName, vCreator,
				SupportedModelType.VENSIM.name(), vDescr, mpId.getUUIdVal(),
				SystemProperties.IS_VISIBLE);
		return new ModelVersionID(mvId);
	}

	@Override
	public ModelVersionID createAnylogicModelVersion(String vName,
			String vCreator, String vDescr, ModelProjectID mpId,
			StorageI storage) throws Exception {
		UUID mvId = storage.addModelVersion(vName, vCreator,
				SupportedModelType.ANYLOGIC.toString(), vDescr,
				mpId.getUUIdVal(), SystemProperties.IS_VISIBLE);
		return new ModelVersionID(mvId);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.cs.usask.ca.silver.api.businesslogic.ModelVersionI#
	 * createModelVersionFromLocalInputFile(java.lang.String, java.lang.String,
	 * java.lang.String,
	 * edu.cs.usask.ca.silver.businesslogic.ids.ModelProjectID,
	 * java.lang.String, int)
	 */
	@Override
	public ModelVersionID createGenericModelVersionFromLocalInputFile(
			String vName, String vCreator, String vDescr, ModelProjectID mpId,
			String sourceFileLocation, int visibility, StorageI storage)
			throws Exception {

		ModelVersionID result;
		boolean error = false;

		try {
			SilverBLTransactionManager.startTransaction();

			result = createGenericModelVersion(vName, vCreator, vDescr, mpId,
					storage);
			addSourceToModelVersion(result, sourceFileLocation, storage);
		} catch (Exception e) {
			error = true;
			throw e;
		} finally {
			try {
				SilverBLTransactionManager.closeTransaction(error);
			} catch (Exception e) {
				throw e;
			}
		}
		return result;
	}

	@Override
	public ModelVersionID createAnylogicModelVersionFromLocalInputFile(
			String vName, String vCreator, String vDescr, ModelProjectID mpId,
			String sourceFileLocation, String classFiles, int visibility,
			StorageI storage) throws Exception {

		ModelVersionID result;
		boolean error = false;

		try {
			SilverBLTransactionManager.startTransaction();
			result = createAnylogicModelVersion(vName, vCreator, vDescr, mpId,
					storage);
			interpretAnylogicSourceFileAndPackClassFilesToModelVersion(result,
					sourceFileLocation, classFiles, storage);
		} catch (Exception e) {
			error = true;
			throw e;
		} finally {
			try {
				SilverBLTransactionManager.closeTransaction(error);
			} catch (Exception e) {
				throw e;
			}
		}
		return result;
	}

	@Override
	public ModelVersionID createVensimModelVersionFromLocalInputFile(
			String vName, String vCreator, String vDescr, ModelProjectID mpId,
			String sourceFileLocation, int visibility, StorageI storage)
			throws Exception, UnsatisfiedLinkError {

		ModelVersionID result;
		boolean error = false;

		try {
			SilverBLTransactionManager.startTransaction();

			result = createVensimModelVersion(vName, vCreator, vDescr, mpId,
					storage);
			interpretVensimSourceFileInModelVersion(result, vName, vCreator,
					sourceFileLocation, storage);
		} catch (java.lang.UnsatisfiedLinkError e1) {
			error = true;
			throw e1;
		}

		catch (Exception e) {
			error = true;
			throw e;
		} finally {
			try {
				SilverBLTransactionManager.closeTransaction(error);
			} catch (Exception e) {
				throw e;
			}
		}
		return result;
	}

	private void interpretVensimSourceFileInModelVersion(ModelVersionID result,
			String name, String creator, String sourceFileLocation,
			StorageI storage) throws Exception {
		boolean error = false;

		try {
			SilverBLTransactionManager.startTransaction();

			// 2. Add a scenario collection (defaultName, creator, defaultDescr,
			// mvId) -> returns scId
			UUID scId = storage.addScenarioCollection("ORIGINAL Sc", creator,
					"Original Scenario Collection - Change Description",
					result.getUUIdVal());

			// 3. Load the sourcefile and parse it
			File sourceFile = new File(sourceFileLocation);
			if (!sourceFile.canRead()) {
				throw new IOException(
						"Attempting to parse source file failed. Could not open: "
								+ sourceFileLocation);
			}

			// 4. Add a default parameter set -> returns psId
			int psId = storage
					.addParameterSet("Original Parameter Set - Change Description");

			// 5. For each parameter parsed from source file, add it (set value
			// and psId)
			String loadModelCommand = "SPECIAL>LOADMODEL|" + sourceFileLocation;
			UUID fUUID = storage.addFile(sourceFile.getName(),
					"Original Source File", sourceFileLocation);

			if (Vensim.command(loadModelCommand) == 1) {
				logger.info("Loading: " + sourceFileLocation + " succeed");
			} else {
				logger.info("Loading: " + sourceFileLocation + " failed");
			}

			String[] constants = Vensim.get_varnames("*",
					Vensim.VARTYPE_CONSTANT);

			RecordUnqualifiedParameters(constants, result, psId, storage);

			// 6. Add the scenario -> returns sId
			// - give it a default name
			// - creator is same as project
			// - default description
			// - set mvId, scId, psId
			UUID sId = storage.addScenario("ORIGINAL Scenario", creator,
					SupportedModelType.VENSIM.toString(),
					"Original Scenario - Change Description",
					result.getUUIdVal(), scId, psId);

			// 7. Set the baseline and original Scenarios for this version to
			// sId
			storage.setMvBaselineScenario(result.getUUIdVal(), sId);
			storage.setMvOriginalScenario(result.getUUIdVal(), sId);

			storage.setMvSourceFileId(result.getUUIdVal(), fUUID);
		} catch (Exception e) {
			error = true;
			throw e;
		} finally {
			try {
				SilverBLTransactionManager.closeTransaction(error);
			} catch (Exception e) {
				throw e;
			}
		}

	}

	// record the unqualified parameter names for this version
	// (i.e.the the parameter names without any subscripts expanded e.g.
	// InitialSusceptible[AgeCategories] or InitialScalar

	private void RecordUnqualifiedParameters(String[] constants,
			ModelVersionID mvId, int psId, StorageI storage) throws Exception {

		for (int i = 0; i < constants.length; i++)
			RecordUnqualifiedParameter(constants[i], mvId, psId, storage);
	}

	// now record an unqualified parameter name e.g.
	// InitialSusceptible[AgeCategories] or InitialScalar
	private void RecordUnqualifiedParameter(String parameterNameUnqualified,
			ModelVersionID mvId, int psId, StorageI storage) throws Exception {
		String[] fullyQualifiedVariableNames = FullyQualifiedNamesFromUnqualifiedVariableName(parameterNameUnqualified);

		// the units and variable types are associated with the UNQUALIFIED
		// variable name -- not the qualified one!!
		String strUnits = StrUnitsForUnqualifiedVariableName(parameterNameUnqualified);
		String strVariableType = StrVariableTypeForUnqualifiedVariableName(parameterNameUnqualified);

		// now record the fully qualified parameter names for this version
		// e.g. InitialSusceptible[Age0To4],InitialSusceptible[Age5To9],
		// InitialScalar

		for (int i = 0; i < fullyQualifiedVariableNames.length; i++)
			RecordFullyQualifiedParameter(fullyQualifiedVariableNames[i],
					strUnits, strVariableType, mvId, psId, storage);
	}

	// give the fully qualified names corresponding to this unqualified name
	// (i.e. the parameter with the subscripts
	// fully expanded.
	// e.g. InitialSusceptible[Age0To4],InitialSusceptible[Age5To9] would be
	// returned for InitialSusceptible
	// and InitialScalar would be returned for InitialScalar
	public String[] FullyQualifiedNamesFromUnqualifiedVariableName(
			String parameterNameUnqualified) {
		String arrayStrExpandedSubscriptsIncludingSurroundingBrackets[] = Vensim
				.get_varattrib(parameterNameUnqualified, Vensim.ATTRIB_SUBALL);

		if (arrayStrExpandedSubscriptsIncludingSurroundingBrackets.length == 0)
			// if the parameter has no subscripts that require expansion, just
			// return it directly
			return new String[] { parameterNameUnqualified };
		else
			// otherwise, return the parameter name with the subscripts (within
			// brackets) as a suffix.
			return CreateSubscriptedParameterFromParameterNameAndFullyQualifiedSubscriptArray(
					parameterNameUnqualified,
					arrayStrExpandedSubscriptsIncludingSurroundingBrackets);
	}

	private String[] CreateSubscriptedParameterFromParameterNameAndFullyQualifiedSubscriptArray(
			String parameterNameUnqualified,
			String[] arrayStrExpandedSubscriptsIncludingSurroundingBrackets) {
		int ctFullyQualifiedSubscriptCombinations = arrayStrExpandedSubscriptsIncludingSurroundingBrackets.length;

		String[] result = new String[ctFullyQualifiedSubscriptCombinations];

		for (int i = 0; i < ctFullyQualifiedSubscriptCombinations; i++)
			result[i] = parameterNameUnqualified
					+ arrayStrExpandedSubscriptsIncludingSurroundingBrackets[i];

		return result;
	}

	// now record a fully qualified parameter name e.g.
	// InitialSusceptible[Age0To4] or InitialScalar

	private void RecordFullyQualifiedParameter(String parameterNameQualified,
			String strUnits, String strType, ModelVersionID mvId, int psId,
			StorageI storage) throws Exception {
		float[] tempValues = new float[2];

		// unpack the variables into a fully qualified form if necessary.
		int result = Vensim.get_val(parameterNameQualified, tempValues);

		if (result == 0) {
			System.out
					.println("get_val  -- failed creating Vensim ModelVersion with status code "
							+ result + " for model version id" + mvId);
		} else {
			float valueDefault = tempValues[0];

			logger.info("default value: " + valueDefault);

			// arguments:
			//
			// pName The name of the parameter (from source file)
			// pUnits The units of a parameter (user defined)
			// pType The type of the parameter (from source file)
			// pClass The class/parent containing this parameter (from
			// source file)
			// pDescr The description of the parameter (user defined)
			// psId The integer id of the parameter set this parameter
			// belongs to
			// pValue The value of the parameter in this parameter set
			// pValComment Comment on the value of the parameter in this
			// parameter set

			storage.addParameter(parameterNameQualified, strUnits, strType, "",
					"DEFAULT - Change description", psId,
					String.valueOf(valueDefault),
					"Original value from source file");
		}
	}

	private String StrUnitsForUnqualifiedVariableName(
			String parameterNameUnqualified) {
		String arrayStrUnits[] = Vensim.get_varattrib(parameterNameUnqualified,
				Vensim.ATTRIB_UNITS);
		if (arrayStrUnits.length > 0)
			return arrayStrUnits[0];
		else
			return "default";
	}

	private String StrVariableTypeForUnqualifiedVariableName(
			String parameterNameUnqualified) throws Exception {
		String arrayStrType[] = Vensim.get_varattrib(parameterNameUnqualified,
				Vensim.ATTRIB_VARTYPE);
		if (arrayStrType.length == 0) {
			throw new Exception(
					"Bug: didn't get any variable type information back for variable "
							+ parameterNameUnqualified
							+ " in call to get_varattrib.");
		} else if (arrayStrType.length > 1) {
			throw new Exception(
					"Bug: Got more than 1 instance of variable type information back for variable "
							+ parameterNameUnqualified
							+ " in call to get_varattrib.");
		} else
			return arrayStrType[0];

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.cs.usask.ca.silver.api.businesslogic.ModelVersionI#
	 * addSourceToModelVersion
	 * (edu.cs.usask.ca.silver.businesslogic.ids.ModelVersionID,
	 * java.lang.String)
	 */
	public void addSourceToModelVersion(ModelVersionID mvId,
			String sourceFileLocation, StorageI storage) throws Exception {

		File sourceFile;
		boolean error = false;

		try {
			SilverBLTransactionManager.startTransaction();

			sourceFile = new File(sourceFileLocation);
			if (!sourceFile.canRead()) {
				throw new IOException(
						"Attempting to parse source file failed. Could not open: "
								+ sourceFileLocation);
			}

			UUID fUUID = storage.addFile(sourceFile.getName(),
					"Original Source File", sourceFileLocation);

			storage.setMvSourceFileId(mvId.getUUIdVal(), fUUID);
		} catch (Exception e) {
			error = true;
			throw e;
		} finally {
			try {
				SilverBLTransactionManager.closeTransaction(error);
			} catch (Exception e) {
				throw e;
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.cs.usask.ca.silver.api.businesslogic.ModelVersionI#
	 * addSourceFileToModelVersion
	 * (edu.cs.usask.ca.silver.businesslogic.ids.ModelVersionID,
	 * java.lang.String)
	 */
	@Override
	public boolean interpretAnylogicSourceFileAndPackClassFilesToModelVersion(
			ModelVersionID mvId, String sourceFileLocation,
			String classFileLocation, StorageI storage) throws Exception {

		boolean error = false;

		try {
			SilverBLTransactionManager.startTransaction();
			String creator = storage.getMvCreator(mvId.getUUIdVal());
			// 2. Add a scenario collection (defaultName, creator, defaultDescr,
			// mvId) -> returns scId
			UUID scId = storage.addScenarioCollection("ORIGINAL Sc", creator,
					"Original Scenario Collection - Change Description",
					mvId.getUUIdVal());

			// 3. Load the sourcefile and parse it
			File sourceFile = new File(sourceFileLocation);
			if (!sourceFile.canRead()) {
				throw new IOException(
						"Attempting to parse source file failed. Could not open: "
								+ sourceFileLocation);
			}
			alpParser = new AlpFileReader();
			NodeList paramList = alpParser.buildParameterSetDOMFromAlp(
					sourceFile).getElementsByTagName("Parameter");

			// 4. Add a default parameter set -> returns psId
			int psId = storage
					.addParameterSet("Original Parameter Set - Change Description");

			// 5. For each parameter parsed from source file, add it (set value
			// and psId)
			Node tempItem;
			String[] paramAttrs = new String[4]; // There are 4 attributes for
			// each Parameter: name, def
			// val, type, parent object

			for (int i = 0; i < paramList.getLength(); i++) {
				tempItem = paramList.item(i);
				NodeList kids = tempItem.getChildNodes();
				for (int j = 0; j < kids.getLength(); j++) {
					Element tempKid = (Element) kids.item(j);
					paramAttrs[j] = tempKid.getTextContent();
				}
				storage.addParameter(paramAttrs[ParameterEnum.NAME.index],
						"UNITS - change", paramAttrs[ParameterEnum.TYPE.index],
						paramAttrs[ParameterEnum.CLASS.index],
						"DEFAULT - Change description", psId,
						paramAttrs[ParameterEnum.VALUE.index],
						"Original value from source file");
			}

			// 6. Add the scenario -> returns sId
			// - give it a default name
			// - creator is same as project
			// - default description
			// - set mvId, scId, psId
			// 6. Add the scenario -> returns sId
			// - give it a default name
			// - creator is same as project
			// - default description
			// - set mvId, scId, psId
			UUID sId = storage.addScenario("ORIGINAL Scenario", creator,
					SupportedModelType.ANYLOGIC.name(),
					"Original Scenario - Change Description",
					mvId.getUUIdVal(), scId, psId);

			// 7. Set the baseline and original Scenarios for this version to
			// sId
			storage.setMvBaselineScenario(mvId.getUUIdVal(), sId);
			storage.setMvOriginalScenario(mvId.getUUIdVal(), sId);

			// 8. Add the sourcefile into DB (name is last bit of filename,
			// defaultDescr, data) -> returns fId
			UUID fId = storage.addFile(sourceFile.getName(),
					"Original Source File", sourceFileLocation);

			String name = storage.getMvName(mvId.getUUIdVal());

			File jarFile = JarBuilder.createJar(classFileLocation, name);

			if (!jarFile.canRead()) {
				throw new IOException(
						"Attempting to load jar file failed. Could not open: "
								+ classFileLocation);
			}

			UUID jfId = storage.addFile(jarFile.getName(), "Original JAR File",
					jarFile.getAbsolutePath());

			// TODO the following to log
			logger.info("Added " + jarFile.getAbsolutePath() + " "
					+ jarFile.getName());

			// 9. Add Input Jar File to ORIGINAL Scenario;
			storage.addFFileToScenarioAsInputFile(jfId, sId);

			// 10. Set source file id for this mvId
			storage.setMvSourceFileId(mvId.getUUIdVal(), fId);

		} catch (Exception e) {
			error = true;
			throw e;
		} finally {
			try {
				SilverBLTransactionManager.closeTransaction(error);
			} catch (Exception e) {
				throw e;
			}
		}

		return !error;

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ModelVersionI#getModelVersionAsXML
	 * (edu.cs.usask.ca.silver.businesslogic.ids.ModelVersionID)
	 */
	public String getModelVersionAsXML(ModelVersionID mvId, StorageI storage)
			throws Exception {
		return storage.getModelVersionAsXML(mvId.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ModelVersionI#getName(edu.cs
	 * .usask.ca.silver.businesslogic.ids.ModelVersionID)
	 */
	public String getName(ModelVersionID mvId, StorageI storage)
			throws Exception {
		return storage.getMvName(mvId.getUUIdVal());
	}

	public String getType(ModelVersionID mvId, StorageI storage)
			throws Exception {
		return storage.getMvType(mvId.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ModelVersionI#getDescription
	 * (edu.cs.usask.ca.silver.businesslogic.ids.ModelVersionID)
	 */
	public String getDescription(ModelVersionID mvId, StorageI storage)
			throws Exception {
		return storage.getMvDescription(mvId.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ModelVersionI#getCreator(edu
	 * .cs.usask.ca.silver.businesslogic.ids.ModelVersionID)
	 */
	public String getCreator(ModelVersionID mvId, StorageI storage)
			throws Exception {
		return storage.getMvCreator(mvId.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ModelVersionI#getCreationDate
	 * (edu.cs.usask.ca.silver.businesslogic.ids.ModelVersionID)
	 */
	public Date getCreationDate(ModelVersionID mvId, StorageI storage)
			throws Exception {
		return storage.getMvCreationDate(mvId.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ModelVersionI#getCreationTime
	 * (edu.cs.usask.ca.silver.businesslogic.ids.ModelVersionID)
	 */
	public Date getCreationTime(ModelVersionID mvId, StorageI storage)
			throws Exception {
		return storage.getMvCreationTime(mvId.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ModelVersionI#getAssociatedFileIds
	 * (edu.cs.usask.ca.silver.businesslogic.ids.ModelVersionID)
	 */
	public FileID[] getAssociatedFileIds(ModelVersionID mvId, StorageI storage)
			throws Exception {
		ArrayList<UUID> result;
		result = storage.getModelVersionAssociatedFileIds(mvId.getUUIdVal());
		FileID[] ids = new FileID[result.size()];

		int i = 0;
		Iterator<UUID> e = result.iterator();
		while (e.hasNext()) {
			ids[i++] = new FileID(e.next());
		}

		return ids;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ModelVersionI#getParentProjectId
	 * (edu.cs.usask.ca.silver.businesslogic.ids.ModelVersionID)
	 */
	public ModelProjectID getParentProjectId(ModelVersionID mvId,
			StorageI storage) throws Exception {
		UUID id = storage.getMvParentProjectId(mvId.getUUIdVal());
		return new ModelProjectID(id);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ModelVersionI#getSourceFileId
	 * (edu.cs.usask.ca.silver.businesslogic.ids.ModelVersionID)
	 */
	public FileID getSourceFileId(ModelVersionID mvId, StorageI storage)
			throws Exception {
		UUID id = storage.getMvSourceFileId(mvId.getUUIdVal());

		return new FileID(id);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ModelVersionI#getSourceFileName
	 * (edu.cs.usask.ca.silver.businesslogic.ids.ModelVersionID)
	 */
	public String getSourceFileName(ModelVersionID mvId, StorageI storage)
			throws Exception {
		return storage.getMvSourceFileName(mvId.getUUIdVal());
	}

	public ScenarioID getOriginalScenarioId(ModelVersionID mvId,
			StorageI storage) throws Exception {
		UUID sId = storage.getMvOriginalScenarioId(mvId.getUUIdVal());
		return new ScenarioID(sId);
	}

	public ScenarioID getBaselineScenarioId(ModelVersionID mvId,
			StorageI storage) throws Exception {
		UUID sId = null;
		try {
			sId = storage.getMvBaselineScenarioId(mvId.getUUIdVal());
			if (sId == null)
				return null;

		} catch (NullPointerException npe) {
			logger.info("no baseline is set");
		} catch (SilverBusinessLogicErrorException lee) {
			logger.info("logic error");
		}
		return new ScenarioID(sId);
	}

	public void recreateOriginalSourceFileToDisk(ModelVersionID mvId,
			String destLoc, StorageI storage) throws Exception {
		FileID sourceFId = getSourceFileId(mvId, storage);
		UUID fUUID = sourceFId.getUUIdVal();

		storage.getFFileToLocalStorage(fUUID, new File(destLoc));
	}

	public void recreateOriginalInputFilesToDisk(ModelVersionID mvId,
			String destLoc, StorageI storage) throws Exception {
		// get the ORIGINAL SCENARIO to this Model Version
		ScenarioID sId = getOriginalScenarioId(mvId, storage);
		ArrayList<UUID> result = storage.getScenarioInputFileIds(sId
				.getUUIdVal());

		FileID fId = null;

		// iterate through the input files and output them.
		Iterator<UUID> e = result.iterator();
		while (e.hasNext()) {
			fId = new FileID(e.next());
			storage.getFFileToLocalStorage(fId.getUUIdVal(), new File(destLoc));
		}

	}

	// public ScenarioID getMostRecentScenarioId(ModelVersionID mvId)
	// throws Exception {
	// int mvIdId = mvId.getIdVal();
	// int id = storage.getMvMostRecentScenarioId(
	// mvIdId);
	// ScenarioID result = new ScenarioID(id);
	// return result;
	// }

	public ScenarioCollectionID[] getScenarioCollectionIds(ModelVersionID mvId,
			StorageI storage) throws Exception {
		ArrayList<UUID> result = storage.getMvScenarioCollectionIds(mvId
				.getUUIdVal());
		ScenarioCollectionID[] ids = new ScenarioCollectionID[result.size()];

		int i = 0;
		Iterator<UUID> e = result.iterator();
		while (e.hasNext()) {
			ids[i++] = new ScenarioCollectionID(e.next());
		}
		return ids;
	}

	public boolean setName(ModelVersionID mvId, String name, StorageI storage)
			throws Exception {
		return storage.setMvName(mvId.getUUIdVal(), name);
	}

	public boolean setType(ModelVersionID mvId, String type, StorageI storage)
			throws Exception {
		return storage.setMvType(mvId.getUUIdVal(), type);
	}

	public boolean setDescription(ModelVersionID mvId, String description,
			StorageI storage) throws Exception {
		return storage.setMvDescription(mvId.getUUIdVal(), description);
	}

	public boolean setBaselineScenario(ModelVersionID mvId, ScenarioID sId,
			StorageI storage) throws Exception {
		return storage.setMvBaselineScenario(mvId.getUUIdVal(),
				sId.getUUIdVal());
	}

	public boolean deleteVersion(ModelVersionID mvId, StorageI storage)
			throws Exception {
		return storage.deleteVersion(mvId.getUUIdVal());
	}

	public ScenarioCollectionID duplicateScenarioCollection(
			ScenarioCollectionID scId, ModelVersionID mvId, StorageI storage)
			throws Exception {
		UUID scID = storage.duplicateScenarioCollection(scId.getUUIdVal(),
				mvId.getUUIdVal());
		return new ScenarioCollectionID(scID);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.ModelVersionI#setOriginalScenario
	 * (edu.cs.usask.ca.silver.businesslogic.ids.ModelVersionID,
	 * edu.cs.usask.ca.silver.businesslogic.ids.ScenarioID)
	 */
	public boolean setOriginalScenario(ModelVersionID mvId, ScenarioID sId,
			StorageI storage) throws Exception {
		return storage.setMvOriginalScenario(mvId.getUUIdVal(),
				sId.getUUIdVal());

	}

}